#include <QByteArray> // for QByteArray, operator==
#include <QDate> // for QDate
#include <QDateTime> // for QDateTime
-#include <QList> // for QList<>::const_iterator, QList
#include <QString> // for QString, operator!=, operator==
#include <QTime> // for QTime
#include <Qt> // for CaseInsensitive
#define DBG(a, b) if ((GDB_DEBUG & (a)) && (b))
+
+inline bool operator==(const GdbFormat::WptNameKey& lhs, const GdbFormat::WptNameKey &rhs) noexcept
+{
+ return lhs.shortname.compare(rhs.shortname, Qt::CaseInsensitive) == 0;
+}
+
+inline bool operator==(const GdbFormat::WptNamePosnKey& lhs, const GdbFormat::WptNamePosnKey &rhs) noexcept
+{
+ return
+ (lhs.shortname.compare(rhs.shortname, Qt::CaseInsensitive) == 0) &&
+ lhs.lat == rhs.lat &&
+ lhs.lon == rhs.lon;
+}
+
void
-GdbFormat::gdb_flush_waypt_queue(QList<Waypoint*>* Q)
+GdbFormat::gdb_flush_waypt_queue(WptNamePosnHash& Q)
{
- while (!Q->isEmpty()) {
- const Waypoint* wpt = Q->takeFirst();
+ for (auto it = Q.cbegin(), end = Q.cend(); it != end; ++it) {
+ const Waypoint* wpt = it.value();
if (wpt->extra_data) {
// wpt->extra_data may be holding a pointer to a QString, courtesy
// the grossness at the end of write_waypoint_cb().
}
delete wpt;
}
+ Q = WptNamePosnHash();
}
#if GDB_DEBUG
return qres;
}
-Waypoint*
-GdbFormat::gdb_find_wayptq(const QList<Waypoint*>* Q, const Waypoint* wpt, const char exact)
+Waypoint* GdbFormat::gdb_find_wayptq(const WptNameHash& Q, const Waypoint* wpt)
{
- QString name = wpt->shortname;
- foreach (Waypoint* tmp, *Q) {
- if (name.compare(tmp->shortname,Qt::CaseInsensitive) == 0) {
- if (! exact) {
- return tmp;
- }
+ if (Q.contains(wpt->shortname)) {
+ return Q.value(wpt->shortname);
+ }
+ return nullptr;
+}
- if ((tmp->latitude == wpt->latitude) &&
- (tmp->longitude == wpt->longitude)) {
- return tmp;
- }
- }
+Waypoint* GdbFormat::gdb_find_wayptq(const WptNamePosnHash& Q, const Waypoint* wpt)
+{
+ auto key = WptNamePosnKey(wpt->shortname, wpt->latitude, wpt->longitude);
+ if (Q.contains(key)) {
+ return Q.value(key);
}
return nullptr;
}
Waypoint*
-GdbFormat::gdb_reader_find_waypt(const Waypoint* wpt, const char exact) const
+GdbFormat::gdb_reader_find_waypt(const Waypoint* wpt, bool exact) const
{
- Waypoint* res = gdb_find_wayptq(&wayptq_in, wpt, exact);
- if (res == nullptr) {
- res = gdb_find_wayptq(&wayptq_in_hidden, wpt, exact);
+ Waypoint* res;
+ if (exact) {
+ res = gdb_find_wayptq(waypt_nameposn_in_hash, wpt);
+ if (res == nullptr) {
+ res = gdb_find_wayptq(waypt_nameposn_in_hidden_hash, wpt);
+ }
+ } else {
+ res = gdb_find_wayptq(waypt_name_in_hash, wpt);
+ if (res == nullptr) {
+ res = gdb_find_wayptq(waypt_name_in_hidden_hash, wpt);
+ }
}
return res;
}
Waypoint*
GdbFormat::gdb_add_route_waypt(route_head* rte, Waypoint* ref, const int wpt_class) const
{
- Waypoint* tmp = gdb_reader_find_waypt(ref, 1);
+ Waypoint* tmp = gdb_reader_find_waypt(ref, true);
if (tmp == nullptr) {
tmp = find_waypt_by_name(ref->shortname);
if (tmp == nullptr) {
if (links == 0) {
/* Without links we need all information from wpt */
- Waypoint* tmp = gdb_reader_find_waypt(wpt, 0);
+ Waypoint* tmp = gdb_reader_find_waypt(wpt, false);
if (tmp != nullptr) {
delete wpt;
wpt = new Waypoint(*tmp);
ftmp = gbfopen_le(nullptr, "wb", MYNAME);
read_file_header();
- wayptq_in.clear();
- wayptq_in_hidden.clear();
+ waypt_nameposn_in_hash.clear();
+ waypt_name_in_hash.clear();
+ waypt_nameposn_in_hidden_hash.clear();
+ waypt_name_in_hidden_hash.clear();
bool via = gdb_opt_via;
bool drop_wpt = gdb_opt_drop_hidden_wpt;
GdbFormat::rd_deinit()
{
disp_summary(fin);
- gdb_flush_waypt_queue(&wayptq_in);
- gdb_flush_waypt_queue(&wayptq_in_hidden);
+ gdb_flush_waypt_queue(waypt_nameposn_in_hash);
+ waypt_name_in_hash = WptNameHash(); /* values already flushed */
+ gdb_flush_waypt_queue(waypt_nameposn_in_hidden_hash);
+ waypt_name_in_hidden_hash = WptNameHash(); /* values already flushed */
gbfclose(ftmp);
gbfclose(fin);
}
if (!gdb_hide_wpt || (wpt_class == 0)) {
waypt_add(wpt);
auto* dupe = new Waypoint(*wpt);
- wayptq_in.append(dupe);
+ waypt_nameposn_in_hash.insert(WptNamePosnKey(wpt->shortname, wpt->latitude, wpt->longitude), dupe);
+ waypt_name_in_hash.insert(wpt->shortname, dupe);
} else {
- wayptq_in_hidden.append(wpt);
+ waypt_nameposn_in_hidden_hash.insert(WptNamePosnKey(wpt->shortname, wpt->latitude, wpt->longitude), wpt);
+ waypt_name_in_hidden_hash.insert(wpt->shortname, wpt);
}
break;
case 'R':
gdb_check_waypt(next);
}
- Waypoint* test = gdb_find_wayptq(&wayptq_out, wpt, 1);
+ Waypoint* test = gdb_find_wayptq(waypt_nameposn_out_hash, wpt);
if (test != nullptr) {
wpt = test;
} else {
/* do this when backup always happens in main */
// but, but, casting away the const here is wrong...
(const_cast<Waypoint*>(refpt))->shortname = refpt->shortname.trimmed();
- Waypoint* test = gdb_find_wayptq(&wayptq_out, refpt, 1);
+ Waypoint* test = gdb_find_wayptq(waypt_nameposn_out_hash, refpt);
if (refpt->HasUrlLink() && test && test->HasUrlLink() && route_flag == 0) {
UrlLink orig_link = refpt->GetUrlLink();
auto* wpt = new Waypoint(*refpt);
gdb_check_waypt(wpt);
- wayptq_out.append(wpt);
+ waypt_nameposn_out_hash.insert(WptNamePosnKey(wpt->shortname, wpt->latitude, wpt->longitude), wpt);
gbfile* fsave = fout;
fout = ftmp;
gdb_category = strtol(gdb_opt_bitcategory, nullptr, 0);
}
- wayptq_out.clear();
+ waypt_nameposn_out_hash.clear();
short_h = nullptr;
waypt_ct = 0;
GdbFormat::wr_deinit()
{
disp_summary(fout);
- gdb_flush_waypt_queue(&wayptq_out);
+ gdb_flush_waypt_queue(waypt_nameposn_out_hash);
mkshort_del_handle(&short_h);
gbfclose(fout);
gbfclose(ftmp);
#ifndef GDB_H_INCLUDED_
#define GDB_H_INCLUDED_
-#include <QList> // for QList
+#include <QHash> // for QHash<>::const_iterator, QHash<>::key_iterator, qHash, qHashMulti, QHash
#include <QString> // for QString
#include <QStringView> // for QStringView
#include <QVector> // for QVector
+#include <QtGlobal> // for QT_VERSION, QT_VERSION_CHECK
#include "defs.h" // for arglist_t, Waypoint, route_head, ARGTYPE_BOOL, ARGTYPE_INT, ARG_NOMINMAX, bounds, FF_CAP_RW_ALL, ff_cap, ff_type, ff_type_file, short_handle
#include "format.h" // for Format
void write() override;
void wr_deinit() override;
+ /* Types */
+
+ // see https://www.kdab.com/how-to-declare-a-qhash-overload/
+ class WptNamePosnKey;
+ using WptNamePosnHash = QHash<WptNamePosnKey, Waypoint*>;
+ class WptNamePosnKey {
+ public:
+ WptNamePosnKey(const QString& name, double lt, double ln) : shortname(name), lat(lt), lon(ln) {}
+
+ friend qhash_result_t qHash(const WptNamePosnKey &c, qhash_result_t seed = 0) noexcept
+ {
+#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
+ return qHashMulti(seed, c.shortname.toUpper(), c.lat, c.lon);
+#else
+ /*
+ * As noted in above refeference
+ * QtPrivate::QHashCombine is private API, but does not require any special buildsystem magic;
+ * it’s in <qhashfunctions.h>, a public header.
+ */
+ QtPrivate::QHashCombine hash;
+
+ seed = hash(seed, c.shortname.toUpper());
+ seed = hash(seed, c.lat);
+ seed = hash(seed, c.lon);
+ return seed;
+#endif
+ }
+
+ QString shortname;
+ double lat{};
+ double lon{};
+ };
+
+ class WptNameKey;
+ using WptNameHash = QHash<WptNameKey, Waypoint*>;
+ class WptNameKey {
+ public:
+ WptNameKey(const QString& name) : shortname(name) {} /* converting constructor */
+
+ friend qhash_result_t qHash(const WptNameKey &c, qhash_result_t seed = 0) noexcept
+ {
+ return qHash(c.shortname.toUpper(), seed);
+ }
+
+ QString shortname;
+ };
+
private:
/* Constants */
/* Member Functions */
- static void gdb_flush_waypt_queue(QList<Waypoint*>* Q);
+ static void gdb_flush_waypt_queue(WptNamePosnHash& Q);
void disp_summary(const gbfile* f) const;
QString fread_cstr() const;
static char* gdb_fread_cstr(gbfile* file_in);
QString gdb_fread_strlist() const;
- static Waypoint* gdb_find_wayptq(const QList<Waypoint*>* Q, const Waypoint* wpt, char exact);
- Waypoint* gdb_reader_find_waypt(const Waypoint* wpt, char exact) const;
+ static Waypoint* gdb_find_wayptq(const WptNameHash& Q, const Waypoint* wpt);
+ static Waypoint* gdb_find_wayptq(const WptNamePosnHash& Q, const Waypoint* wpt);
+ Waypoint* gdb_reader_find_waypt(const Waypoint* wpt, bool exact) const;
Waypoint* gdb_add_route_waypt(route_head* rte, Waypoint* ref, int wpt_class) const;
static QString gdb_to_ISO8601_duration(unsigned int seconds);
void gdb_write_cstr(QStringView a = QStringView()) const;
bool gdb_hide_wpt{};
bool gdb_hide_rpt{};
- QList<Waypoint*> wayptq_in, wayptq_out, wayptq_in_hidden;
+ WptNamePosnHash waypt_nameposn_in_hash;
+ WptNameHash waypt_name_in_hash;
+ WptNamePosnHash waypt_nameposn_in_hidden_hash;
+ WptNameHash waypt_name_in_hidden_hash;
+ WptNamePosnHash waypt_nameposn_out_hash;
short_handle short_h{};
char* gdb_opt_category{};